<?php
class WebSessionManager extends ORMManager implements SessionObjectInterface{
	
    private $cookieName = 'ui';
	private $webClient = null;
	private $webClientId = null;
	private $expiriedDays = 1825; // 5 years 
	
	function __construct() {
		parent::__construct();
	    // чистим от старой куки
	    if (isset($_COOKIE['uid'])){
	        setcookie('uid',null,time() - 3600,'/');
	    }
	    
	    // пока нету веб-сессии, проверяем, нужно ли ее устанавливать
	    if (!$this->_inCookie()){
	        setcookie('chk','1',time() + 3600,'/'); // cтавим тестовый кук
	    }
	     
        if(isset($_COOKIE['chk'])){
            $_SESSION['webSessionAvailable'] = 1; // можно устанавливать веб-сессию
	        setcookie('chk',null,time() - 3600,'/'); // ансетим тестовый кук
        }    

        // если разрешен сетап сессии;
        // если сессии не существует - то устанавливаем ее,
        // существует - проверяем
	    if (!$_SESSION['webClientHacker'] && $_SESSION['webSessionAvailable']) {
        	        if ($_SESSION['webClientId']){
        	            
        	            if (!$this->_inCookie()){
            	           $this->_restoreCookieFromSession();
            	        }
            	        
        	            if (($_SESSION['person_id'] && ($_SESSION['person_id'] != $_SESSION['webPersonId']))) {
            	           $this->_checkWebClient();
        	            }
        	            
        	        } else {
        	            $this->_checkWebClient();
        	        }   
         }
	}
	
	public function getWebClient()
	{
        return $this->webClient;
	}
	
	public function getWebClientId()
	{
        return $this->webClientId;	    
	}
   
	private function _getNewWebClient() {
	    $webClientCode = $this->_getNewWebClientCode();
		$webSessionDB = new Passport_WebSessionDBO();
		$webSessionDB->clientId = $_SESSION['person_id'];
		$webSessionDB->webClientCode = $webClientCode;
		$webSessionDB->save();
		if($webSessionDB->webClientId) {
			$lastInsert = $webSessionDB->webClientId;
			$this->webClient = array('id'=>$lastInsert,'code'=>$webClientCode);
            $this->webClientId = $lastInsert;
            $this->clientId = $webSessionDB->clientId;
            
            // update of session date table
			$webSessionDateDB = new Passport_WebSessionDateDBO();
			$webSessionDateDB->webSessionDate = time();
			$webSessionDateDB->maxSessionId = $lastInsert;
			$webSessionDateDB->save();
			
			$this->_setWebClientToCookie();
			$this->_setWebClientSession();
		} 
	}
	
   /**
    * Check if webClient cookie exists
    *
    * @return boolean true if cookie exist or false if not
    */
	
	private function _inCookie() {
		return isset($_COOKIE[$this->cookieName]);
	}
	
   /**
    * Checking webClient info (from cookie)
    * if no cookie - create new webClient
    * but if cookie is wrong - adding webClient to Hack List
    *
    * @return bool false if wrong cookie params, or true if all good
    */
	
	private function _checkWebClient() {
		
	    $this->_parseCookie();
	    
	    if ($this->webClientId){ // web session present
	    	$webSessionDB = $this->getTable('Passport_WebSessionDBO')->find($this->webClientId);
    	    if (is_object($webSessionDB) && ($webSessionDB->webClientCode != $this->webClient['code'])) {
    	        // maybe hacker attack 
    	        $this->_addToHackList();
    	    } else {
    	        if (Ria_Client::getInstance()->Client->isAuthed() && ($webSessionDB->clientId!=Ria_Client::getInstance()->Client->clientID)) { 
                    $webSessionDB->clientId = Ria_Client::getInstance()->Client->clientID;
    	            $webSessionDB->save();
    	        }
    	        $this->clientId = $webSessionDB->clientId;
                $this->_setWebClientSession();
    	    }
    	    
	    } else { // web session not found
	        $this->_getNewWebClient();
	    }
	}
	
	private function _addToHackList(){
	    $webSessionHackDB = new Passport_WebSessionHackDBO();
		$webSessionHackDB->webSessionId = $this->webClient['id'];
		$webSessionHackDB->ip = REMOTE_ADDR;
		$webSessionHackDB->date = time();
		$webSessionHackDB->save();
		
		$_SESSION['webClientHacker'] = true;
	}
	
	private function _getNewWebClientCode() {
		return rand(0,2147483647);
	}
	
	private function _convertCodeToHex($value,$size=8){
		$konvValue = base_convert($value,10,16);
		return str_pad($konvValue,$size,'0',STR_PAD_LEFT);
	}
	
	private  function _parseCookie() {
		
	    $webClientId = 0;
	    $webClientCode = 0;
	    
	    if($this->_inCookie()) {
			$cookieValue = $_COOKIE[$this->cookieName];
			$webClientId = base_convert(substr($cookieValue,0,strlen($cookieValue)-8),16,10)*1; 
			$webClientCode = base_convert(substr($cookieValue,-8),16,10)*1;
		}
		   $this->webClient = array (
		   							  'id' => $webClientId,
		                              'code' =>  $webClientCode
		                            );

		   $this->webClientId = $webClientId; 
	}
	
	private function _setWebClientToCookie() {
		
			$webClientId = base_convert($this->webClient['id'],10,16);
			$webClientCode = $this->_convertCodeToHex($this->webClient['code']);
			
			setcookie($this->cookieName,$webClientId.$webClientCode,time()+ $this->expiriedDays*86400,'/');
	}
	
	private function _setWebClientSession()
	{
        $_SESSION['webPersonId'] = $this->clientId;
        $_SESSION['webClientId'] = $this->webClient['id'];
        $_SESSION['webClientCode'] = $this->webClient['code'];
	}
	
	private function _detectBot()
	{
	  return preg_match('#bot#i',$_SERVER['HTTP_USER_AGENT']);   
	}
	
	private function _restoreCookieFromSession()
	{
	    $this->webClient = array(
        							'id' => $_SESSION['webClientId'],
	                                'code' => $_SESSION['webClientCode']
	                            );
	    $this->_setWebClientToCookie();                        
	}
	
	public function getObjectState(){
  		return '';
  	}
  
  	public function setObjectState($objectState){
  		
  	}
}
?>